/**
 * 
 */
package fr.gfi.agraf.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import fr.gfi.agraf.exception.AgrafException;
import fr.gfi.agraf.persistence.dao.IEtatDAO;
import fr.gfi.agraf.persistence.dao.ISaisieDAO;
import fr.gfi.agraf.persistence.dao.ITacheDAO;
import fr.gfi.agraf.persistence.entity.Etat;
import fr.gfi.agraf.persistence.entity.Saisie;
import fr.gfi.agraf.persistence.entity.Tache;
import fr.gfi.agraf.service.ISaisieService;
import fr.gfi.agraf.vue.bean.SaisieDTO;

/**
 * @author Zakaria
 *
 */
@Service("SaisieService")
public class SaisieService implements ISaisieService {

	private static final String ERREUR_SAISIE_EXIST = "erreur.saisie.exist";

	private static final String ERREUR_SAISIE_NOTDELETE = "erreur.saisie.notdelete";

	private static final String ERREUR_TACHE_NOTEXIST = "erreur.tache.notexist";

	@Autowired
	private ITacheDAO tacheDAO;

	@Autowired
	private IEtatDAO etatDAO;

	@Autowired
	private ISaisieDAO saisieDAO;

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.gfi.agraf.service.ISaisieService#ajouterSaisies(java.util.List)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public void ajouterSaisies(final List<SaisieDTO> saisieDTOList) throws AgrafException {
		if (!CollectionUtils.isEmpty(saisieDTOList)) {
			// Créer une liste d'ids pour récupere les taches
			final List<Long> idTacheList = getIdTacheList(saisieDTOList);
			// Récupere une map de id/taches
			final Map<Long, Tache> tacheMap = tacheDAO.getTachesMapByIds(idTacheList);
			// Récupere les etats
			final Map<Long, Etat> etatMap = etatDAO.getEtatsMap();
			// Pour chaque saisieDTO, on créé une entity
			for (final SaisieDTO saisieDTO : saisieDTOList) {

				traitementSaisie(tacheMap, etatMap, saisieDTO);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.gfi.agraf.service.ISaisieService#supprimerSaisies(java.util.List)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public void supprimerSaisies(final List<Long> idSaisieList) throws AgrafException {
		if (!CollectionUtils.isEmpty(idSaisieList)) {
			final int rows = saisieDAO.supprimerSaisieByIds(idSaisieList);
			if (rows != idSaisieList.size()) {
				throw new AgrafException(ERREUR_SAISIE_NOTDELETE);
			}
		}
	}

	/**
	 * Créé l'entity pour la bdd
	 * 
	 * @param tacheMap
	 * @param etatMap
	 * @param saisieDTO
	 * @throws AgrafException
	 */
	private void traitementSaisie(final Map<Long, Tache> tacheMap, final Map<Long, Etat> etatMap,
			final SaisieDTO saisieDTO) throws AgrafException {
		final Long idTache = saisieDTO.getIdTache();
		// Récupere la tache concerné
		final Tache tache = tacheMap.get(idTache);
		if (tache == null) {
			throw new AgrafException(ERREUR_TACHE_NOTEXIST,idTache);
		}
		final Set<Saisie> listeSaisiesTache = tache.getListeSaisies();
		// Verifier la date de la saisie
		verifierDateSaisie(saisieDTO, listeSaisiesTache);
		// Créer l'entity
		final Saisie saisie = new Saisie();
		saisie.setConsomme(saisieDTO.getConsomme());
		saisie.setDate(saisieDTO.getDate());
		saisie.setEtat(etatMap.get(saisieDTO.getEtat().getId()));
		saisie.setRaf(saisieDTO.getRaf());
		saisie.setTache(tache);
		if (saisieDTO.isValidee()) {
			saisie.setValidee('1');
		} else {
			saisie.setValidee('0');
		}
		final String newCommentaire = saisieDTO.getCommentaire();
		// Ajoute le commentaire à la tache
		if (StringUtils.isNotBlank(newCommentaire)) {
			final String oldCommentaire = tache.getCommentaire();
			tache.setCommentaire(oldCommentaire.concat(" | ").concat(newCommentaire));
		}
		listeSaisiesTache.add(saisie);
	}

	/**
	 * Crée une liste de tache id
	 * 
	 * @param saisieDTOList
	 * @return
	 */
	private List<Long> getIdTacheList(final List<SaisieDTO> saisieDTOList) {
		final List<Long> idTacheList = new ArrayList<Long>();
		for (final SaisieDTO saisieDTO : saisieDTOList) {
			idTacheList.add(saisieDTO.getIdTache());
		}
		return idTacheList;
	}

	/**
	 * Verifie si une saisie existe déjà à cette date
	 * 
	 * @param saisieDTO
	 * @param listeSaisiesTache
	 * @throws AgrafException
	 */
	private void verifierDateSaisie(final SaisieDTO saisieDTO, final Set<Saisie> listeSaisiesTache)
			throws AgrafException {
		if (!CollectionUtils.isEmpty(listeSaisiesTache)) {
			for (final Saisie saisie : listeSaisiesTache) {
				if (DateUtils.isSameDay(saisie.getDate(), saisieDTO.getDate())) {
					throw new AgrafException(ERREUR_SAISIE_EXIST);
				}
			}
		}
	}

	/**
	 * @return the tacheDAO
	 */
	public ITacheDAO getTacheDAO() {
		return tacheDAO;
	}

	/**
	 * @param tacheDAO
	 *            the tacheDAO to set
	 */
	public void setTacheDAO(final ITacheDAO tacheDAO) {
		this.tacheDAO = tacheDAO;
	}

	/**
	 * @return the etatDAO
	 */
	public IEtatDAO getEtatDAO() {
		return etatDAO;
	}

	/**
	 * @param etatDAO
	 *            the etatDAO to set
	 */
	public void setEtatDAO(final IEtatDAO etatDAO) {
		this.etatDAO = etatDAO;
	}

	/**
	 * @return the saisieDAO
	 */
	public ISaisieDAO getSaisieDAO() {
		return saisieDAO;
	}

	/**
	 * @param saisieDAO
	 *            the saisieDAO to set
	 */
	public void setSaisieDAO(final ISaisieDAO saisieDAO) {
		this.saisieDAO = saisieDAO;
	}
}
